unit mongo;

interface

uses
  Winsock2,
  bson;

const
  MONGO_MAJOR = 0;
  MONGO_MINOR = 4;
  MONGO_PATCH = 0;

  MONGO_OK = 0;
  MONGO_ERROR = -1;

  MONGO_DEFAULT_PORT = 27017;

type
  TMongoError = (
    meMongoConnSuccess = 0, // Connection success!
    meMongoConnNoSocket,    // Could not create a socket.
    meMongoConnFail,        // An error occured while calling connect().
    meMongoConnAddrFail,    // An error occured while calling getaddrinfo().
    meMongoConnNotMaster,   // Warning: connected to a non-master node (read-only).
    meMongoConnBadSetName,  // Given rs name doesn't match this replica set.
    meMongoConnNoPrimary,   // Can't find primary in replica set. Connection closed.

    meMongoIOError,         // An error occurred while reading or writing on the socket.
    meMongoReadSizeError,   // The response is not the expected length.
    meMongoCommandFailed,   // The command returned with 'ok' value of 0.
    meMongoBsonInvalid,     // BSON not valid for the specified op.
    meMongoBsonNotFinished  // BSON object has not been finished.
  );

  TMongoCursorError = (
    mceMongoCursorExhausted, // The cursor has no more results.
    mceMongoCursorInvalid,   // The cursor has timed out or is not recognized.
    mceMongoCursorPending,   // Tailable cursor still alive but no data.
    mceMongoCursorQueryFail, // The server returned an '$err' object, indicating query failure.
                             // See conn->lasterrcode and conn->lasterrstr for details.
    mceMongoCursorBsonError  // Something is wrong with the BSON provided. See conn->err
                             // for details.
  );

  TMongoCursorFlag = (
    mcfMongoCursorMustFree = 0, // mongo_cursor_destroy should free cursor.
    mcfMongoCursorQuerySent = 1 // Initial query has been sent.
  );
  TMongoCursorFlags = set of TMongoCursorFlag;

  TMongoIndexOpt = (
    mioMongoIndexUnique = 0,
    mioMongoIndexDropDups = 2,
    mioMongoIndexBackground = 3,
    mioMongoIndexSparse = 4
  );
  TMongoIndexOpts = set of TMongoIndexOpt;

  TMongoUpdateOpt = (
    muoMongoUpdateUpsert = 0,
    muoMongoUpdateMulti = 1,
    muoMongoUpdateBasic = 2
  );
  TMongoUpdateOpts = set of TMongoUpdateOpt;

  TMongoCursorOpt = (
    mcoMongoTailable = 1,        // Create a tailable cursor.
    mcoMongoSlaveOk = 2,         // Allow queries on a non-primary node.
    mcoMongoNoCursorTimeout = 4, // Disable cursor timeouts.
    mcoMongoAwaitData = 5,       // Momentarily block for more data.
    mcoMongoExhaust = 6,         // Stream in multiple 'more' packages.
    mcoMongoPartial = 7          // Allow reads even if a shard is down.
  );
  TMongoCursorOpts = set of TMongoCursorOpt;

  TMongoOperations = (
    moMongoOpMsg = 1000,
    moMongoOpUpdate = 2001,
    moMongoOpInsert = 2002,
    moMongoOpQuery = 2004,
    moMongoOpGetMore = 2005,
    moMongoOpDelete = 2006,
    moMongoOpKillCursors = 2007
  );

  TMongoHeader = packed record
    len: Integer;
    id: Integer;
    responseTo: Integer;
    op: Integer;
  end;

  TMongoMessage = packed record
    head: TMongoHeader;
    data: Byte;
  end;

  TMongoReplyFields = packed record
    flag: Integer; // FIX THIS COMMENT non-zero on failure
    cursorID: Int64;
    start: Integer;
    num: Integer;
  end;

  PMongoReply = ^TMongoReply;
  TMongoReply = packed record
    head: TMongoHeader;
    fields: TMongoReplyFields;
    objs: Byte;
  end;

  PMongoHostPort = ^TMongoHostPort;
  TMongoHostPort = record
    host: string;
    port: Integer;
    next: PMongoHostPort;
  end;

  PMongoReplset = ^TMongoReplset;
  TMongoReplset = record
    seeds: PMongoHostPort;      // List of seeds provided by the user.
    hosts: PMongoHostPort;      // List of host/ports given by the replica set
    name: string;               // Name of the replica set.
    primary_connected: Boolean; // Primary node connection status.
  end;

  PMongo = ^TMongo;
  TMongo = record
    primary: PMongoHostPort;  // Primary connection info.
    replset: PMongoReplset;   // replset object if connected to a replica set.
    sock: TSocket;            // Socket file descriptor.
    flags: Integer;           // Flags on this connection object.
    conn_timeout_ms: Integer; // Connection timeout in milliseconds.
    op_timeout_ms: Integer;   // Read and write timeout in milliseconds.
    connected: Boolean;       // Connection status.

    err: TMongoError;         // Most recent driver error code.
    errstr: string;           // String version of most recent driver error code.
    lasterrcode: Integer;     // getlasterror given by the server on calls.
    lasterrstr: string;       // getlasterror string generated by server.
  end;

  TMongoCursor = record
    reply: PMongoReply;        // reply is owned by cursor
    conn: PMongo;              // connection is *not* owned by cursor
    ns: string;                // owned by cursor
    flags: TMongoCursorFlags;  // Flags used internally by this drivers.
    seen: Integer;             // Number returned so far.
    current: TBson;            // This cursor's current bson object.
    err: TMongoCursorError;    // Errors on this cursor.
    query: PBson;
    fields: PBson;
    options: TMongoCursorOpts; // Bitfield containing cursor options.
    limit: Integer;
    skip: Integer;
  end;

implementation

end.
